#include <cmath>
#include <iostream>
#include "Vector.h"

const CVector CVector::mS_Right = CVector(1.0f, 0.0f, 0.0f);
const CVector CVector::mS_Up = CVector(0.0f, 1.0f, 0.0f);
const CVector CVector::mS_Forward = CVector(0.0f, 0.0f, 1.0f);

CVector::CVector(void):m_X(0.0f), m_Y(0.0f), m_Z(0.0f)
{
}


CVector::~CVector(void)
{
}

CVector::CVector(float _x, float _y, float _z = 0.0f)
{
	m_X = _x;
	m_Y = _y;
	m_Z = _z;
}

CVector::CVector(const CVector& _vec)
{
	m_X = _vec.m_X;
	m_Y = _vec.m_Y;
	m_Z = _vec.m_Z;
}

float	CVector::Length()
{
	return sqrt(pow(m_X, 2.0f) + pow(m_Y, 2.0f) + pow(m_Z, 2.0f));
}

float	CVector::LengthSquare()
{
	return (float) pow(sqrt(pow(m_X, 2.0f) + pow(m_Y, 2.0f) + pow(m_Z, 2.0f)) , 2.0);
}

CVector	CVector::operator+ (CVector _vec)
{
	CVector result;
	result.SetX(m_X + _vec.GetX());
	result.SetY(m_Y + _vec.GetY());
	result.SetZ(m_Z + _vec.GetZ());
	
	return result;
}

CVector	CVector::operator- (CVector _vec)
{
	CVector result;
	result.SetX(m_X - _vec.GetX());
	result.SetY(m_Y - _vec.GetY());
	result.SetZ(m_Z - _vec.GetZ());
	
	return result;
}

CVector	CVector::operator* (float _val)
{
	CVector result;
	result.SetX(m_X * _val);
	result.SetY(m_Y * _val);
	result.SetZ(m_Z * _val);
	
	return result;
}

CVector	CVector::operator/ (float _val)
{
	CVector result = CVector(*this);

	if (_val != 0)
	{
		result.SetX(m_X / _val);
		result.SetY(m_Y / _val);
		result.SetZ(m_Z / _val);
	}

	return result;
}

CVector	CVector::operator*  (CVector _vec)
{
	return CVector(m_X * _vec.GetX(), m_Y * _vec.GetY(), m_Z * _vec.GetZ());
}

CVector	CVector::operator/  (CVector _vec)
{
	return CVector(m_X / _vec.GetX(), m_Y / _vec.GetY(), m_Z / _vec.GetZ());
}

CVector	CVector::operator+= (CVector _vec)
{
	return CVector(m_X + _vec.GetX(), m_Y + _vec.GetY(), m_Z + _vec.GetZ());			// TODO
}

CVector	CVector::operator-= (CVector _vec)
{
	return CVector(m_X - _vec.GetX(), m_Y - _vec.GetY(), m_Z - _vec.GetZ());				// TODO
}

CVector	CVector::operator*= (CVector _vec)
{
	return CVector(m_X * _vec.GetX(), m_Y * _vec.GetY(), m_Z * _vec.GetZ());			// TODO
}

CVector	CVector::operator/= (CVector _vec)
{
	return CVector(m_X / _vec.GetX(), m_Y / _vec.GetY(), m_Z / _vec.GetZ());			// TODO
}

float	CVector::DotProduct(CVector _vecA, CVector _vecB)
{
	return _vecA.GetX() * _vecB.GetX() + _vecA.GetY() * _vecB.GetY() + _vecA.GetZ() * _vecB.GetZ();
}

CVector	CVector::CrossProduct(CVector _vecA, CVector _vecB)
{
	return CVector(
					_vecA.GetY() * _vecB.GetZ() - _vecA.GetZ() * _vecB.GetY(),
					_vecA.GetZ() * _vecB.GetX() - _vecA.GetX() * _vecB.GetZ(),
					_vecA.GetX() * _vecB.GetY() - _vecA.GetY() * _vecB.GetX()
					);
}

CVector CVector::Normalize()
{
	float length = Length();

	if (length > 0)
		return CVector(m_X / length, m_Y / length, m_Z / length);

	return CVector(*this);
}

void CVector::Print()
{
	std::cout << std::endl << "[" << m_X << ", " << m_Y << ", " << m_Z << "]";
}

CVector CVector::Reflect()
{
	return CVector();	// TODO!
}